#include "EbnModelController.h"
#include <iostream>
#include "EbnModel.h"
#include "EbnWorldStateManager.h"
#include "EbnActionManager.h"
#include "EbnModelFactory.h"

CEbnActionTrigger::CEbnActionTrigger(string actionName, string worldStateName, float truthValue)
{
    mActionName = actionName;
    mWorldStateName = worldStateName;
    mTruthValue = truthValue;
}

CEbnActionTrigger::~CEbnActionTrigger(void)
{

}

string CEbnActionTrigger::getActionName(void)
{
    return mActionName;
}

string CEbnActionTrigger::getWorldStateName(void)
{
    return mWorldStateName;
}

float CEbnActionTrigger::getTruthValue(void)
{
    return mTruthValue;
}

bool CEbnActionTrigger::isAction(string actionName)
{
    if(0 == mActionName.compare(actionName))
    {
        return true;
    }

    return false;
}

bool CEbnActionTrigger::isWorldState(string worldStateName)
{
    if (0 == mWorldStateName.compare(worldStateName))
    {
        return true;
    }

    return false;
}

CEbnModelController::CEbnModelController(QObject * parent) :
    QObject(parent)
{
    mpModel = CEbnModel::getModel();
    mpWorldStateManager = new CEbnWorldStateManager();
    mpActionManager = new CEbnActionManager();

    mpModelFactory = new CEbnModelFactory(this);

    mControllerStarted = false;
    mControllerRunning = false;

}

CEbnModelController::~CEbnModelController()
{
    vector<CEbnActionTrigger *>::iterator it;
    CEbnActionTrigger * pActionTrigger = NULL;
    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        pActionTrigger = (* it);

        if (pActionTrigger)
        {
            delete pActionTrigger;
            pActionTrigger = NULL;
        }
    }

    mActionTriggerList.clear();

    if (mpWorldStateManager)
    {
        delete mpWorldStateManager;
        mpWorldStateManager = NULL;
    }

    if (mpActionManager)
    {
        delete mpActionManager;
        mpActionManager = NULL;
    }

    if (mpModel)
    {
        delete mpModel;
        mpModel = NULL;
    }
}

void CEbnModelController::initializeModel(void)
{

}

void CEbnModelController::uninitializeModel(void)
{

}

void CEbnModelController::start(void)
{
    qDebug("CEbnModelController::start");
    if (false == mControllerStarted)
    {

        initializeModel();

        if (mpModel)
        {
            connect(mpModel->getActionMsgReceiver(), SIGNAL(postActionMsg(string)), this, SLOT(receiveMsgFromModel(string)));

            qDebug("starting ");
            mpModel->start();
        }

        mControllerStarted = true;
    }

}

void CEbnModelController::stop(void)
{
    qDebug("CEbnModelController::stop");
    if (mControllerStarted)
    {
        // pause before stop
        pause();


        if (mpModel)
        {
            qDebug("stopping ");
            mpModel->stop();

            disconnect(mpModel->getActionMsgReceiver(), SIGNAL(postActionMsg(string)), this, SLOT(receiveMsgFromModel(string)));

        }

        uninitializeModel();

        clearActionTrigger();

        mControllerStarted = false;

    }

}

void CEbnModelController::run(void)
{
    qDebug("CEbnModelController::run");
    if (false == mControllerStarted)
    {
        return;
    }

    if (false == mControllerRunning)
    {
        if (mpModel)
        {
            mpModel->run();
        }

        mControllerRunning = true;
    }
}

void CEbnModelController::pause(void)
{
    qDebug("CEbnModelController::pause");
    if (false == mControllerStarted)
    {
        return;
    }

    if (mControllerRunning)
    {
        if (mpModel)
        {
            mpModel->pause();
        }

        mControllerRunning = false;

    }
}


void CEbnModelController::receiveMsgFromModel(string msgName)
{
    cout << "Ebn Model Thread post --> " << msgName << "\n";

    onMsgReceived(msgName);

    doActionTrigger(msgName);

    emit postMsg(msgName);
}

void CEbnModelController::onMsgReceived(string msgName)
{
}

void CEbnModelController::addActionTrigger(string actionName, string worldStateName, float truthValue)
{
    CEbnActionTrigger * actionTrigger = new CEbnActionTrigger(actionName, worldStateName, truthValue);

    mActionTriggerList.push_back(actionTrigger);
}

void CEbnModelController::removeActionTrigger(string actionName, string worldStateName)
{
    bool exist = hasActionTrigger(actionName, worldStateName);

    if (false == exist)
    {
        return;
    }

    vector<CEbnActionTrigger *>::iterator it;
    CEbnActionTrigger * pActionTrigger = NULL;

    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        if((* it)->isAction(actionName)
                && (* it)->isWorldState(worldStateName))
        {
            pActionTrigger = (* it);

            mActionTriggerList.erase(it);
        }
    }

    if (pActionTrigger)
    {
        delete pActionTrigger;
        pActionTrigger = NULL;
    }
}

void CEbnModelController::clearActionTrigger(void)
{
    vector<CEbnActionTrigger *>::iterator it;
    CEbnActionTrigger * pActionTrigger = NULL;

    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        pActionTrigger = (* it);

        if (pActionTrigger)
        {
            delete pActionTrigger;
            pActionTrigger = NULL;
        }

    }

    mActionTriggerList.clear();


}

float CEbnModelController::getActionTriggerValue(string actionName, string worldStateName)
{
    vector<CEbnActionTrigger *>::iterator it;

    CEbnActionTrigger * pActionTrigger = NULL;

    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        pActionTrigger = (* it);

        if (pActionTrigger->isAction(actionName)
                && pActionTrigger->isWorldState(worldStateName))
        {
            return pActionTrigger->getTruthValue();
        }
    }

    return 0;
}

CEbnActionTrigger * CEbnModelController::getActionTrigger(string actionName, string worldStateName)
{
    vector<CEbnActionTrigger *>::iterator it;

    CEbnActionTrigger * pActionTrigger = NULL;

    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        pActionTrigger = (* it);

        if (pActionTrigger->isAction(actionName)
                && pActionTrigger->isWorldState(worldStateName))
        {
            return pActionTrigger;
        }
    }

    return NULL;
}

bool CEbnModelController::hasActionTrigger(string actionName, string worldStateName)
{
    CEbnActionTrigger * pActionTrigger = getActionTrigger(actionName, worldStateName);

    if (NULL == pActionTrigger)
    {
        return false;
    }
    else
    {
        return true;
    }
}

void CEbnModelController::doActionTrigger(string actionName)
{
    vector<CEbnActionTrigger *>::iterator it;

    CEbnActionTrigger * pActionTrigger = NULL;

    for (it = mActionTriggerList.begin(); it != mActionTriggerList.end(); it++)
    {
        pActionTrigger = (* it);

        if (pActionTrigger->isAction(actionName))
        {
            mpWorldStateManager->setWorldStateValue(pActionTrigger->getWorldStateName(),
                                                    pActionTrigger->getTruthValue());
        }
    }
}

void CEbnModelController::loadModelFile(const QString & filename)
{
    if (mpModelFactory)
    {
        mpModelFactory->loadFile(filename);
    }
}
